package com.googlecode.roleaccesscontrol.uc.user;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.roleaccesscontrol.entity.User;

@Repository
@Transactional
public class UserRepository {

	@Autowired
	private SessionFactory sessionFactory;

	public List<User> listUsers(UserFilter filter, int firstResult, int maxResults,
			String orderProperty, boolean ascendant) {

		Criteria criteria = createCriteriaWithFilter(filter);
		criteria.setReadOnly(true);
		criteria.setFirstResult(firstResult);
		criteria.setMaxResults(maxResults);
		if (orderProperty != null) {
			criteria.addOrder(ascendant ? Order.asc(orderProperty) : Order.desc(orderProperty));
		}
		return criteria.list();
	}

	public int count(UserFilter filter) {
		Object count = createCriteriaWithFilter(filter).setProjection(Projections.rowCount())
				.uniqueResult();
		return ((Long) count).intValue();
	}

	public User getById(Long id) {
		return (User) getSession().get(User.class, id);
	}

	private Criteria createCriteriaWithFilter(UserFilter filter) {
		Criteria criteria = getSession().createCriteria(User.class);

		if (filter != null && filter.user != null) {
			if (filter.user.getActive() != null)
				criteria.add(Restrictions.eq("active", filter.user.getActive()));
			if (filter.user.getName() != null)
				criteria.add(Restrictions.ilike("name", filter.user.getName(), MatchMode.ANYWHERE));
			if (filter.user.getFullName() != null)
				criteria.add(Restrictions.ilike("fullName", filter.user.getFullName(),
						MatchMode.ANYWHERE));
		}

		Criteria profileCriteria = null;
		if (filter != null && filter.application != null) {
			profileCriteria = criteria.createCriteria("profiles");
			profileCriteria.createCriteria("application").add(
					Restrictions.idEq(filter.application.getId()));
		}

		if (filter != null && filter.profile != null) {
			if (profileCriteria == null) {
				profileCriteria = criteria.createCriteria("profiles");
			}
			profileCriteria.add(Restrictions.idEq(filter.profile.getId()));
		}

		return criteria;
	}

	@Transactional
	public void save(User user) {
		getSession().save(user);
	}	

	protected Session getSession() {
		return SessionFactoryUtils.getSession(sessionFactory, true);
	}

}
